package org.youyee.game.pathFinding
{
	import flash.utils.Dictionary;

	/**
	 * 逻辑地图对象 
	 * @author youyee
	 * @version 2.0
	 */	
	public class PathMap
	{
		private var _nodes:Vector.<PathNode>;
		private var _illegalNodes:Dictionary;
		private var _nodesLength:int = 0;
		
		private var _width:int;
		private var _height:int;
		
		private var _maxX:int;
		private var _maxY:int;
		
		/**
		 * 构造函数 
		 * @param width 地图的逻辑宽度
		 * @param height 地图的逻辑高度
		 * 
		 */		
		public function PathMap(width:int=10, height:int=10)
		{
			this._width = width;
			this._height = height;
			
			this._maxX = width - 1;
			this._maxY = height - 1;
			
			this._nodesLength = width * height;
			generateNodes();
		}
		
		private function generateNodes():void
		{
			this._nodes = new Vector.<PathNode>();
			
			for (var i:int=0; i<_nodesLength; ++i)
			{
				var x:int = i % width;
				var y:int = int(i / _width);
				this._nodes.push(new PathNode(x, y));
			}
		}
		
		/**
		 * 获取地图中所有合法的路径节点队列 （此接口出于内存性能考虑，不建议使用，如果需要获取节点长度，请直接使用numPathNodes接口）
		 * @return 
		 * 
		 */		
		public function get pathNodes():Vector.<PathNode>
		{
			return this._nodes;
		}
		
		/**
		 * 获取地图中合法节点的总数 
		 * @return 
		 * 
		 */		
		public function get numPathNodes():int
		{
			return this._nodesLength;
		}
		
		/**
		 * 获取地图的逻辑宽度 
		 * @return 
		 * 
		 */		
		public function get width():int
		{
			return this._width;
		}
		
		/**
		 * 获取地图的逻辑高速 
		 * @return 
		 * 
		 */		
		public function get height():int
		{
			return this._height;
		}
		
		/**
		 * 通过位置获取相应的节点 
		 * @param x 逻辑横轴坐标
		 * @param y 逻辑纵轴坐标
		 * @param illegalPathNode 是否为合法节点
		 * @return 
		 * 
		 */		
		public function getPathNodeByPosition(x:int, y:int, illegalPathNode:Boolean=true):PathNode
		{
			if (x < 0 || y <0 || x > _maxX || y > _maxY)
			{
				if (illegalPathNode)
				{
					_illegalNodes = _illegalNodes || new Dictionary();
					var p:PathNode = _illegalNodes[x + "_" + y] as PathNode;
					if (p)
					{
						return p;
					}
					else
					{
						p = new PathNode(x, y);
						_illegalNodes[p.key] = p;
						return p;
					}
				}
				
				return null;
			}
			
			var index:int = x + y * this._width;
			return this._nodes[index];
		}
		
		/**
		 * 是否为合法位置 
		 * @param x 逻辑横轴位置
		 * @param y 逻辑纵轴位置
		 * @return 
		 * 
		 */		
		public function isLigalPosition(x:int, y:int):Boolean
		{
			return !(x < 0 || y <0 || x > _maxX || y > _maxY);
		}
		
		/**
		 * 获取一个节点周围的节点 
		 * @param node 需要被获取的节点
		 * @param clockWise 是否为顺时针取点
		 * @return 
		 * 
		 */		
		public function getAroundNodes(node:PathNode, clockWise:Boolean=true):Array/*of PathNode*/
		{
			var result:Array = [];
			
			if (clockWise)
			{
				if (node.aroundNodesClockWise)
				{
					result = null;
					return node.aroundNodesClockWise;
				}
				
				if (node.x > 0)
				{
					result.push(getPathNodeByPosition(node.x - 1, node.y));
				}
				
				if (node.y > 0)
				{
					result.push(getPathNodeByPosition(node.x, node.y - 1));
				}
				
				if (node.x < _maxX)
				{
					result.push(getPathNodeByPosition(node.x + 1, node.y));
				}
				
				if (node.y < _maxY)
				{
					result.push(getPathNodeByPosition(node.x, node.y + 1));
				}
				
				node.aroundNodesClockWise = result;
			}
			else
			{
				if (node.aroundNodesCounterClockWise)
				{
					result = null;
					return node.aroundNodesCounterClockWise;
				}
				if (node.x > 0)
				{
					result.push(getPathNodeByPosition(node.x - 1, node.y));
				}
				
				if (node.y < _maxY)
				{
					result.push(getPathNodeByPosition(node.x, node.y + 1));
				}
				
				if (node.x < _maxX)
				{
					result.push(getPathNodeByPosition(node.x + 1, node.y));
				}
				
				if (node.y > 0)
				{
					result.push(getPathNodeByPosition(node.x, node.y - 1));
				}
				
				node.aroundNodesCounterClockWise = result;
			}
			
			return result;
		}
		
		/**
		 * 将一个节点集合内的所有点都设置为障碍 
		 * @param nodeArray
		 * 
		 */		
		public function setBarriers(nodeArray:Array):void
		{
			var len:int = nodeArray.length;
			var p:PathNode;
			
			for (var i:int=0; i<len; ++i)
			{
				p = nodeArray[i] as PathNode;
				
				if (p)
				{
					p.isBarrier = true;
				}
			}
		}
		
		/**
		 * 清除地图中的所有障碍 
		 * 
		 */		
		public function clearAllBarriers():void
		{
			for (var i:int=0; i<_nodesLength; ++i)
			{
				if (_nodes[i])
				{
					_nodes[i].isBarrier = false;
				}
			}
		}
		
		/**
		 * 销毁此对象 
		 * 
		 */		
		public function destroy():void
		{
			for (var i:int=0; i<_nodesLength; ++i)
			{
				if (_nodes[i])
				{
					_nodes[i].destroy();
				}
			}
			
			var node:PathNode;
			
			for (var j:* in _illegalNodes)
			{
				node = _illegalNodes[j] as PathNode;
				
				if (node)
				{
					node.destroy();
				}
			}
			
			node = null;
		}
	}
}